import { define } from 'cydon'
import { countCRByStatus, countLockedPost, getLastCR, getPost, updateImg } from '../models/post'
import { getTag } from '../models/tag'
import { getDays } from '../utils'
import { countTag, hexColor } from '../utils/helper'
import { API, Post } from '../api'

/** 帖子缩略图 */
@define('post-thumb')
export class PostThumb extends HTMLElement {
	/** 帖子 */
	post = <Post>{ id: 0 }

	img!: HTMLImageElement

	get pid() {
		return this.post.id
	}
	set pid(id) {
		if (id != this.pid) {
			this.post.id = id
			getPost(id).then((post) => {
				if (!post)
					return
				(<Post>post).id = id
				this.post = <Post>post
				this.updateBorder(<Post>post)
				updateImg(this.img, post)
			})
		}
	}

	connectedCallback() {
		this.img = this.querySelector('img')!
	}

	/** 更新边框 */
	async updateBorder(post: Post) {
		this.style.borderBottom = '1px solid #' + hexColor(
			await getHeat(post.id, post.tags),
			0.954 ** getDays(post.updated_at),
			await getUV(post.tags))
		this.style.borderTop = '1px solid #' + getColor(
			await countCRByStatus(post.id, 2),
			await countCRByStatus(post.id, 3),
			Math.sign(await countLockedPost(post.id, new Date))
		)
		const date = new Date(Date.now() - 6048e5)
		const last7dCR: { tags: string } = await getLastCR(post.id, 2, date) ||
			{ tags: '' }
		this.style.borderLeft = '1px solid #' + getColor(
			await getHeat(post.id, last7dCR.tags),
			0.954 ** getDays(post.created_at),
			await getUV(last7dCR.tags)
		)
		const lastCR = await getLastCR(post.id, 2)
		const y = getDays(lastCR?.updated_at)
		this.style.borderRight = '1px solid #' + hexColor(
			r(await countCRByStatus(post.id, 1)),
			2 / (y + 2),
			await getUV(lastCR?.tags)
		)
	}
}

declare global {
	interface HTMLElementTagNameMap {
		'post-thumb': PostThumb
	}
}

/**
 * 获取帖子热度
 * @param pid 帖子ID
 * @returns 热度
 */
async function getHeat(id: number, tags: string) {
	const views = await API.getDailyViews([id])
	return r((views[0] | 0) + countTag(tags) * 2)
}

/** 获取标签串独特值 */
async function getUV(tags?: string) {
	let z = 0
	if (tags) {
		const p = tags.split(' ').map(tag => getTag(tag)),
			dt = await API.getTagCountDelta(tags)
		for (let i = 0; i < p.length; i++)
			z += Math.log(((await p[i])?.count | 0) + (dt[i] | 0))
	}
	return 1 - 2 / Math.PI * Math.atan(z / countTag(tags))
}

// sin(arctan(ln(x+1)))
const r = (x: number) => Math.sin(Math.atan(Math.log1p(x)))

// rgb(sin(arctan(ln(x+1))),sin(arctan(ln(y+1))),z)
const getColor = (x: number, y: number, z: number) =>
	hexColor(r(x), Math.sin(Math.atan(Math.log1p(y))), z)
